<script setup lang="ts">
import ToolView from "@/modules/tools/layout/tool-view.vue";
import Grid from "@/components/framework/grid.vue";
import { useLocalStorage } from "@vueuse/core";
import { computed, onMounted, ref, shallowRef } from "vue";
import { downloadArtifact, listRepos, searchMavenRepo } from "./maven-search.service.ts";
import { type MavenArtifactInfo, type MavenRepoInfo, type MavenRepoSearchOptions } from "./types.ts";
import { hc } from "@/framework/vue/util/render.ts";
import { DownloadOutlined, ReloadOutlined, SearchOutlined } from "@ant-design/icons-vue";
import { showMessageAndPrint } from "@/framework/util/log.ts";
import VTable from "@/components/framework/v-table.tsx";
import VTableColumn from "@/components/framework/v-table-column.tsx";
import ArtifactDetailModal from "./artifact-detail-modal.vue";
import { useLocalRef, useLocalShallowRef } from "@/framework/vue/hooks/state.ts";

const queryTypes = [
  { value: "keyword", label: "关键字" },
  { value: "gav", label: "GAV" },
];
const repos = shallowRef<MavenRepoInfo[]>([]);
const repoOptions = computed(() => {
  const options = repos.value.map(repo => ({ value: repo.repoId, label: repo.repoName }));
  options.unshift({ value: "all", label: "全部" });
  return options;
});

onMounted(() => {
  listRepos()
    .then(list => {
      repos.value = list;
    })
    .catch(showMessageAndPrint);
});

const keywordHistory = useLocalShallowRef<string[]>("tools.maven-search.keywordHistory", []);

const saveKeywordHistory = (kw: string) => {
  if (!keywordHistory.value.includes(kw)) {
    const list = [kw, ...keywordHistory.value];
    keywordHistory.value = list.slice(0, 10);
  }
};
const defaultFormState = (): MavenRepoSearchOptions => ({
  queryType: "keyword",
  repoId: "all",
  keyword: "",
  groupId: "",
  artifactId: "",
  version: "",
});

const formState = useLocalStorage("tools.maven-search.input", defaultFormState(), { deep: true });

const reset = () => {
  formState.value = defaultFormState();
};

function isInvalid(str: string) {
  return /[^\x20-\x7E]/.test(str) || /[#%;]/.test(str); // 匹配 ASCII 可打印字符范围外的字符
}

const loading = ref(false);
const filterResult = useLocalRef("tools.maven-search.filterResult", true);
const artifectList = shallowRef<MavenArtifactInfo[]>([]);
const renderList = computed(() => {
  if (filterResult.value) {
    return artifectList.value.filter(it => {
      if (it.version === "unknown") return false;
      if (isInvalid(it.groupId) || isInvalid(it.artifactId) || isInvalid(it.version) || isInvalid(it.fileName)) return false;
      return true;
    });
  }
  return artifectList.value;
});

const handleSearch = async (values: MavenRepoSearchOptions) => {
  try {
    loading.value = true;
    const results = await searchMavenRepo(values);
    artifectList.value = results;

    if (values.queryType === "keyword") {
      const kw = values.keyword?.trim();
      kw && saveKeywordHistory(kw);
    }
  } catch (e) {
    showMessageAndPrint(e);
  } finally {
    loading.value = false;
  }
};

const detailOpen = ref(false);
const detailItem = shallowRef<MavenArtifactInfo>();

const showDetail = (item: MavenArtifactInfo) => {
  detailItem.value = item;
  detailOpen.value = true;
};
</script>

<template>
  <tool-view title="Maven仓库查询" description="maven和gradle仓库查询">
    <grid rows-preset="two-rows-0">
      <div class="ph-10 pv-20">
        <a-form layout="inline" :model="formState" @finish="handleSearch">
          <a-form-item name="queryType">
            <a-radio-group v-model:value="formState.queryType" :options="queryTypes" option-type="button" button-style="solid" />
          </a-form-item>
          <a-form-item name="repoId">
            <div class="w-150">
              <a-select v-model:value="formState.repoId" :options="repoOptions" :dropdown-match-select-width="false" />
            </div>
          </a-form-item>
          <a-form-item>
            <a-tooltip title="过滤结果中有乱码或版本未知等乱七八糟的包">
              <a-checkbox v-model:checked="filterResult">过滤</a-checkbox>
            </a-tooltip>
          </a-form-item>

          <div class="flex flex-1">
            <template v-if="formState.queryType === 'keyword'">
              <div class="flex-1">
                <a-form-item name="keyword" label="关键字">
                  <a-dropdown trigger="focus" placement="bottom">
                    <a-input v-model:value="formState.keyword" placeholder="请输入关键字 . . ." allow-clear />
                    <template #overlay>
                      <div class="bg-container border border-radius box-shadow2 p-10">
                        <a-tag v-for="it in keywordHistory" color="var(--color-primary)" @click="formState.keyword = it">{{ it }}</a-tag>
                      </div>
                    </template>
                  </a-dropdown>
                </a-form-item>
              </div>
            </template>
            <template v-else>
              <div class="flex flex-1 child-flex-1">
                <div>
                  <a-form-item name="groupId" label="G">
                    <a-input v-model:value="formState.groupId" placeholder="请输入groupId" allow-clear class="w-full" />
                  </a-form-item>
                </div>
                <div>
                  <a-form-item name="artifactId" label="A">
                    <a-input v-model:value="formState.artifactId" placeholder="请输入artifactId" allow-clear />
                  </a-form-item>
                </div>
                <div>
                  <a-form-item name="version" label="V">
                    <a-input v-model:value="formState.version" placeholder="请输入version" allow-clear />
                  </a-form-item>
                </div>
              </div>
            </template>
            <a-form-item>
              <a-space>
                <a-button shape="circle" :icon="hc(SearchOutlined)" type="primary" html-type="submit" />
                <a-button shape="circle" :icon="hc(ReloadOutlined)" @click="reset" />
              </a-space>
            </a-form-item>
          </div>
        </a-form>
      </div>
      <div class="select-text">
        <v-table :data-source="renderList" row-key="id" :row-height="40" :loading="loading">
          <v-table-column title="仓库" data-index="repositoryId" width="130px" />
          <v-table-column title="文件名" data-index="fileName">
            <template v-slot="{ record, value }">
              <span class="color-primary hover-underline curp" @click="showDetail(record)">{{ value }}</span>
            </template>
          </v-table-column>
          <v-table-column title="groupId" data-index="groupId" />
          <v-table-column title="artifactId" data-index="artifactId" />
          <v-table-column title="version" data-index="version" />
          <v-table-column title="classifier" data-index="classifier" width="100px" />
          <v-table-column title="packaging" data-index="packaging" width="150px" />
          <v-table-column title="操作" width="80px" align="center">
            <template v-slot="{ record }">
              <a-button type="link" shape="circle" :icon="hc(DownloadOutlined)" @click="downloadArtifact(record)" />
            </template>
          </v-table-column>
        </v-table>
      </div>
    </grid>

    <artifact-detail-modal v-model:open="detailOpen" :artifact="detailItem" />
  </tool-view>
</template>

<style scoped lang="less"></style>
